package ccnt.pvc.scudwaremobile.coop;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.teleal.cling.UpnpService;
import org.teleal.cling.UpnpServiceConfiguration;
import org.teleal.cling.android.AndroidUpnpServiceConfiguration;
import org.teleal.cling.android.AndroidUpnpServiceImpl;
import org.teleal.cling.binding.LocalServiceBindingException;
import org.teleal.cling.binding.annotations.AnnotationLocalServiceBinder;
import org.teleal.cling.controlpoint.ControlPoint;
import org.teleal.cling.model.DefaultServiceManager;
import org.teleal.cling.model.ValidationException;
import org.teleal.cling.model.meta.Device;
import org.teleal.cling.model.meta.DeviceDetails;
import org.teleal.cling.model.meta.DeviceIdentity;
import org.teleal.cling.model.meta.LocalDevice;
import org.teleal.cling.model.meta.LocalService;
import org.teleal.cling.model.meta.ManufacturerDetails;
import org.teleal.cling.model.meta.ModelDetails;
import org.teleal.cling.model.types.DeviceType;
import org.teleal.cling.model.types.ServiceType;
import org.teleal.cling.model.types.UDADeviceType;
import org.teleal.cling.model.types.UDAServiceType;
import org.teleal.cling.model.types.UDN;
import org.teleal.cling.registry.Registry;

import ccnt.pvc.scudwaremobile.utils.Constants.PreferenceKeys;
import ccnt.pvc.scudwaremobile.utils.Constants.PreferenceNames;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.wifi.WifiManager;
import android.os.IBinder;
import android.util.Log;

/**
 * 
 * @author dy
 *
 */
public class ScudwareUPnPServiceImpl extends AndroidUpnpServiceImpl {

	private static final String TAG = ScudwareUPnPServiceImpl.class.getName();
	private LocalDevice scudwareDevice;
	protected Binder binder = new Binder(this);
	
	private String account = "test";
	private String ip = null;
	
	@Override
	public void onCreate() {
		Log.d(TAG, "onCreare:" + TAG);
		super.onCreate();
	}
	
	@Override
	public void onDestroy() {
		Log.d(TAG, "onDestroy:" + TAG);
		super.onDestroy();
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		Log.d(TAG, "onBind:" + TAG);
		return binder;
	}
	
	/**
	 * 获得本机IP地址
	 * @return IP地址
	 */
	private String getLocalIpAddress() {  
		String networkIp = null;
		try {
		    List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
		    for(NetworkInterface iface : interfaces){
		        if(iface.getDisplayName().equals("wlan0")){
		            List<InetAddress> addresses = Collections.list(iface.getInetAddresses());
		            for(InetAddress address : addresses){
		                if(address instanceof Inet4Address){
		                    networkIp = address.getHostAddress();
		                }
		            }
		        }
		    }
		} catch (SocketException e) {
		    e.printStackTrace();
		}
		return networkIp;
	}  
	
	private String getAccount() {
		SharedPreferences preference = getSharedPreferences(
				PreferenceNames.LOGIN_PREFERENCE, MODE_PRIVATE);
		String account = preference.getString(PreferenceKeys.ACCOUNT, "unknown");
		return account;
	}
	
	/**
	 * 允许该设备UPnP被发现
	 */
	private void enableFound() {
		try {
			ip = getLocalIpAddress();
			account = getAccount();
			scudwareDevice = createScudwareDevice();
			upnpService.getRegistry().addDevice(scudwareDevice);
			Log.d(TAG, "enable found");
			
		} catch (LocalServiceBindingException e) {
			e.printStackTrace();
		} catch (ValidationException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 禁止该设备UPnP被发现
	 */
	private void disableFound() {
		upnpService.getRegistry().removeDevice(scudwareDevice);
		Log.d(TAG, "disable found");
	}
	
	/**
	 * 获得附近的ScudwareMobile客户端列表
	 * @return 包含ScudwareMobile信息的map, key=account, value=ip
	 */
	private Map<String, String> getScudwares() {
		Map<String, String> scudwares = new HashMap<String, String>();
		
		// 所有发现的远程设备
		//Collection<RemoteDevice> devices = upnpService.getRegistry().getRemoteDevices();
		Collection<Device> devices = upnpService.getRegistry().getDevices();
		DeviceType type = new UDADeviceType("ScudewareMobile", 1);
		for(Device device : devices) {
			if(device.getType().equals(type)) {
				String modelDetail = device.getDetails().getModelDetails()
						.getModelDescription();
				String details[] = modelDetail.split(";");
				String ip = details[1].split(":")[1];
				String account = details[2].split(":")[1];
				scudwares.put(account, ip);
				Log.d(TAG, device.getDetails().getFriendlyName() + ":ip=" + ip + " account=" + account);
			}
		}
		return scudwares;
	}
	
	/**
	 * 创建ScudewareDevice
	 * @return ScudewareDevice实例
	 * @throws ValidationException
	 * @throws LocalServiceBindingException
	 * @throws IOException
	 */
	private LocalDevice createScudwareDevice() 
			throws ValidationException, LocalServiceBindingException, IOException {
		DeviceIdentity identity =
	            new DeviceIdentity(
	                    UDN.uniqueSystemIdentifier("Scudeware Mobile of " + account)
	            );

	    DeviceType type =
	            new UDADeviceType("ScudewareMobile", 1);

	    DeviceDetails details =
	            new DeviceDetails(
	                    "Scudware Mobile of " + account,
	                    new ManufacturerDetails("CCNT PVC"),
	                    new ModelDetails(
	                            "Scudware Mobile",
	                            "A mobile sensing middleware;IP:" + ip + ";ACCOUNT:" + account,
	                            "v1"
	                    )
	            );

	    LocalService<ServiceOfScudeware> service =
	            new AnnotationLocalServiceBinder().read(ServiceOfScudeware.class);
	    
	    service.setManager(
	            new DefaultServiceManager(service, ServiceOfScudeware.class)
	    );

	    return new LocalDevice(identity, type, details, service);
	}
	
	@Override
	protected AndroidUpnpServiceConfiguration createConfiguration(
			WifiManager wifiManager) {
		return new AndroidUpnpServiceConfiguration(wifiManager) {

			@Override
			public ServiceType[] getExclusiveServiceTypes() {
				// 只接收ServiceOfScudeware服务
				return new ServiceType[] {
					new UDAServiceType("ServiceOfScudeware")	
				};
			}

		};
	}
	
	protected class Binder extends android.os.Binder implements
			ScudwareUPnPService {

		private ScudwareUPnPServiceImpl instance = null;
		
		public Binder(ScudwareUPnPServiceImpl instance) {
			this.instance = instance;
		}
		
		public UpnpService get() {
			return upnpService;
		}

		public UpnpServiceConfiguration getConfiguration() {
			return upnpService.getConfiguration();
		}

		public Registry getRegistry() {
			return upnpService.getRegistry();
		}

		public ControlPoint getControlPoint() {
			return upnpService.getControlPoint();
		}

		@Override
		public void enableFound() {
			instance.enableFound();
		}

		@Override
		public void disableFound() {
			instance.disableFound();
		}

		@Override
		public Map<String, String> getScudwares() {
			return instance.getScudwares();
		}
	}
}
